﻿#include "FileTool.h"
#include "WatchFolder.h"
#include "logprint.h"
#include <cstring>
#include <direct.h>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <windows.h>

//using namespace std;

void FileTool::listFiles(const char *dir, const char *suffix, std::vector<_finddata_t> &files, int countWant)
{
    int countFound = 0;
    char dirNew[MAX_PATH_LEN];
    strcpy_s(dirNew, dir);
    strcat_s(dirNew, suffix); // "\\*.*");    // 在目录后面加上"\\*.*"进行第一次搜索

    intptr_t handle;
    _finddata_t findData;

    handle = _findfirst(dirNew, &findData);
    if (handle == -1) // 检查是否成功
        return;

    do
    {
        if (findData.attrib & _A_SUBDIR)
            continue;
        else
        {
#ifdef PRINT_FILE_INFO
            cout << findData.name << "\t" << findData.size << " bytes."
                 << "\t"
                 << findData.time_write << endl;
#endif
            files.push_back(findData);
            countFound++;

            if (countWant > 0 && countFound == countWant)
                break;
        }

    } while (_findnext(handle, &findData) == 0);

    _findclose(handle); // 关闭搜索句柄

    return;
}

void FileTool::listFilesW(const wchar_t *dir, const wchar_t *suffix, std::vector<_wfinddata64i32_t> &files, int countWant)
{
    int countFound = 0;
    wchar_t dirNew[MAX_PATH_LEN];
    wcscpy_s(dirNew, dir);
    wcscat_s(dirNew, suffix); // "\\*.*");    // 在目录后面加上"\\*.*"进行第一次搜索

    intptr_t handle;
    _wfinddata64i32_t findData;

    handle = _wfindfirst(dirNew, &findData);
    if (handle == -1) // 检查是否成功
        return;

    do
    {
        if (findData.attrib & _A_SUBDIR)
            continue;
        else
        {
#ifdef PRINT_FILE_INFO
            cout << findData.name << "\t" << findData.size << " bytes."
                 << "\t"
                 << findData.time_write << endl;
#endif
            files.push_back(findData);
            countFound++;

            if (countWant > 0 && countFound == countWant)
                break;
        }

    } while (_wfindnext(handle, &findData) == 0);

    _findclose(handle); // 关闭搜索句柄

    return;
}

void FileTool::listFileArray(const char *dir, const char *suffix, std::map<std::string, _finddata_t> &files, size_t want_size, int countWant)
{
    int countFound = 0;
    char dirNew[MAX_PATH_LEN];
    strcpy_s(dirNew, dir);
    strcat_s(dirNew, suffix); // "\\*.*");    // 在目录后面加上"\\*.*"进行第一次搜索

    intptr_t handle;
    _finddata_t findData;

    handle = _findfirst(dirNew, &findData);
    if (handle == -1) // 检查是否成功
        return;

    do
    {
        if (findData.attrib & _A_SUBDIR)
            continue;
        else
        {
#ifdef PRINT_FILE_INFO
            cout << findData.name << "\t" << findData.size << " bytes."
                 << "\t"
                 << findData.time_write << endl;
#endif
            if (want_size != findData.size)
                continue;

            files[std::string(findData.name)] = findData;
            countFound++;

            if (countWant > 0 && countFound == countWant)
                break;
        }

    } while (_findnext(handle, &findData) == 0);

    _findclose(handle); // 关闭搜索句柄

    return;
}

size_t FileTool::GetFileCount(const char *dir, const char *suffix)
{
    size_t countFound = 0;
    char dirNew[MAX_PATH_LEN];
    strcpy_s(dirNew, dir);
    strcat_s(dirNew, suffix); // "\\*.*");    // 在目录后面加上"\\*.*"进行第一次搜索

    intptr_t handle;
    _finddata_t findData;

    handle = _findfirst(dirNew, &findData);
    if (handle == -1) // 检查是否成功
        return 0;

    do
    {
        if (findData.attrib & _A_SUBDIR)
            continue;
        else
        {
#ifdef PRINT_FILE_INFO
            cout << findData.name << "\t" << findData.size << " bytes."
                 << "\t"
                 << findData.time_write << endl;
#endif
            countFound++;
        }

    } while (_findnext(handle, &findData) == 0);

    _findclose(handle); // 关闭搜索句柄

    return countFound;
}

// 从左到右依次判断文件夹是否存在,不存在就创建
// example: /home/root/mkdir/1/2/3/4/
// 注意:最后一个如果是文件夹的话,需要加上 '\' 或者 '/'
int FileTool::createDirectory(const std::wstring &directoryPath)
{
    uint32_t dirPathLen = directoryPath.length();
    if (dirPathLen > MAX_PATH_LEN)
    {
        return -1;
    }

    wchar_t tmpDirPath[MAX_PATH_LEN] = {0};
    for (uint32_t i = 0; i < dirPathLen; ++i)
    {
        tmpDirPath[i] = directoryPath[i];
        if (tmpDirPath[i] == L'\\' || tmpDirPath[i] == L'/')
        {
            if (_waccess(tmpDirPath, 0) != 0)
            {
                int32_t ret = _wmkdir(tmpDirPath);
                if (ret != 0)
                {
                    return ret;
                }
            }
        }
    }
    return 0;
}

bool FileTool::CheckPathValidA(std::string path, bool CreateIt)
{
    auto IsExist = _access(path.c_str(), 0);

    if (0 != IsExist)
    {
        if (CreateIt)
        {
            auto bSuc = createDirectoriesA(path);
            return bSuc;
        }

        return false;
    }
    else
        return true;
}

bool FileTool::getKeyFileNameW(const std::wstring &filename, std::wstring &result)
{
    wchar_t underline = L'_';
    auto pos = filename.find_last_of(underline);

    if (std::string::npos != pos)
    {
        result = filename.substr(0, pos);
        return true;
    }

    return false;
}

bool FileTool::getKeyFileName(const std::string &filename, std::string &result)
{
    auto pos = filename.find_last_of('_');

    if (std::string::npos != pos)
    {
        result = filename.substr(0, pos);
        return true;
    }

    return false;
}

bool FileTool::getPart1FileName(const std::string &filename, std::string &result, char separator)
{
    auto pos = filename.find_first_of(separator);

    if (std::string::npos != pos)
    {
        result = filename.substr(0, pos);
        return true;
    }

    return false;
}

void FileTool::WriteContent2TextFile(const std::string &filePath, const std::string &content)
{
    ofstream ofs;
    ofs.open(filePath, ios::app | ios::ate);

    if (ofs.is_open())
    {
        ofs << content << endl;
        ofs.close();
    }
}

void FileTool::WriteContent2TextFileW(const std::wstring &filePath, const std::wstring &content)
{
    wofstream ofs;
    ofs.open(filePath, ios::app | ios::ate);

    if (ofs.is_open())
    {
        ofs << content << endl;
        ofs.close();
    }
}

bool FileTool::waitFolderChange(std::wstring targetFolder)
{
    DPW(LgLevel::LL_Dbg, L"[%s]: enter.targetFolder:(%s).\n", __FUNCTIONW__, targetFolder.c_str());

    WatchFolder fol;
    bool ret = fol.Init(targetFolder);
    if (!ret)
    {
        DPW(LgLevel::LL_Dbg, L"[%s]: Init fail.return false.\n", __FUNCTIONW__);
        return false;
    }

    auto retVal = fol.BeginMonitorRenameEvent();

    DPW(LgLevel::LL_Dbg, L"[%s]: return retVal:%d..\n", __FUNCTIONW__, retVal);
    return retVal;
}

bool FileTool::CheckPathValid(std::wstring path, bool CreateIt)
{
    auto size = path.size();
    if (size < 1)
    {
        DPW(LgLevel::LL_Error, L"[Error][%s]: path size is 0.return 4.\n", __FUNCTIONW__);
        return false;
    }

    if (_waccess(path.c_str(), 0) != 0)
    {
        if (CreateIt)
        {
            auto bSuc = createDirectory(path);
            return bSuc;
        }

        DPW(LgLevel::LL_Error, L"[Error][%s]: enter.path(%s) is not exist ...\n", __FUNCTIONW__,
            path.c_str());
        return false;
    }

    return true;
}
